package com.girant.logger.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.girant.dict.api.DictApi;
import com.girant.dict.entity.dto.SysDictItemDTO;
import com.girant.logger.config.BoostConfig;
import com.girant.logger.entity.domain.ErrorLogDocumentDO;
import com.girant.logger.entity.dto.ErrorLogExportDTO;
import com.girant.logger.entity.vo.show.ErrorLogExportVO;
import com.girant.logger.mapper.ErrorLogMapper;
import com.girant.logger.service.ErrorlogExportService;
import com.girant.logger.utils.SearchUtil;
import org.apache.logging.log4j.Level;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import static com.girant.logger.config.Constants.DICT_CODE_SERVER;
@Slf4j
@Service
public class ErrorLogExportServiceImpl implements ErrorlogExportService {
    @Autowired
    private ErrorLogMapper ErrorLogMapper;
    @Autowired
    private DictApi dictApi;
    @Autowired
    private BoostConfig boostConfig;

    @Value("${es.min.score:0.2}")
    private Double minScore;

    @Override
    public List<ErrorLogExportVO> exportLog(ErrorLogExportDTO request) {

        // 1.构建查询条件并打印,并且过滤
        LambdaEsQueryWrapper<ErrorLogDocumentDO> wrapper = buildBoolQuery(request);

        if (StrUtil.isNotBlank(request.getKeyword())){
            wrapper.minScore(minScore);
        }

        //2.设置排序条件
        wrapper.orderByDesc(ErrorLogDocumentDO::getOperationTime);

        //3.获得所有数据（不大于10000）
        List<ErrorLogDocumentDO>  documents = ErrorLogMapper.selectList(wrapper);

        //4.获得字典映射
        List<SysDictItemDTO> list = dictApi.getDictList(DICT_CODE_SERVER);
        Map<String, String> map = list.stream().collect(Collectors.toMap(SysDictItemDTO::getDictKey, SysDictItemDTO::getDictLabel));

        //5. 转换为VO
        List<ErrorLogExportVO> records = documents.stream()
                .map(document -> {
                    // 创建VO对象
                    ErrorLogExportVO vo = BeanUtil.copyProperties(document, ErrorLogExportVO.class);
                    // 设置serverNameLabel的字典值
                    vo.setServerNameLabel(
                            map.getOrDefault(document.getServerName(), "") );
                    return vo;
                })
                .collect(Collectors.toList());



        log.info("ES查询总命中数：{}条, 存入Excel的数据：{}条", documents.size());
            return records;
    }


        private LambdaEsQueryWrapper<ErrorLogDocumentDO> buildBoolQuery (ErrorLogExportDTO request){
            LambdaEsQueryWrapper<ErrorLogDocumentDO> wrapper = new LambdaEsQueryWrapper<>();
            if (ObjectUtil.isNotEmpty(request.getOperationStartTime())) {
                wrapper.ge(ErrorLogDocumentDO::getOperationTime, DateUtil.format(request.getOperationStartTime(), DatePattern.NORM_DATETIME_MS_PATTERN));//大于等于，并且转化格式
            }
            // 处理结束时间
            if (ObjectUtil.isNotEmpty(request.getOperationEndTime())) {
                wrapper.le(ErrorLogDocumentDO::getOperationTime, DateUtil.format(request.getOperationEndTime(), DatePattern.NORM_DATETIME_MS_PATTERN));//小于等于，并且转化格式
            }

            // 2. IP模糊匹配（CIDR格式）
            if (StrUtil.isNotBlank(request.getSourceIp())) {
                String cidr = SearchUtil.convertIpPrefixToCidr(request.getSourceIp());
                wrapper.eq(ErrorLogDocumentDO::getSourceIp, cidr,2.0f);
            }
            // 3. LogLevel精确排除杂余数据
            wrapper.eq(ErrorLogDocumentDO::getLogLevel, Level.ERROR.name());

            // 4. traceId/spanId 精确匹配
            if (StrUtil.isNotBlank(request.getTraceId())) {
                wrapper.eq(ErrorLogDocumentDO::getTraceId, request.getTraceId(),2.0f);
            }
            if (StrUtil.isNotBlank(request.getSpanId())) {
                wrapper.eq(ErrorLogDocumentDO::getSpanId, request.getSpanId(),2.0f);
            }
            //5.精确匹配ServerName
            if (StrUtil.isNotBlank(request.getServerName())) {
                wrapper.eq(ErrorLogDocumentDO::getServerName, request.getServerName(),2.0f);
            }

            if (StrUtil.isNotBlank(request.getKeyword())) {
                wrapper.should(w -> w.match(ErrorLogDocumentDO::getErrorInfo, request.getKeyword(), boostConfig.getErrorInfo()));
                wrapper.should(w -> w.match(ErrorLogDocumentDO::getStackTrace, request.getKeyword(), boostConfig.getStackTrace()));
                wrapper.should(w -> w.eq(ErrorLogDocumentDO::getClientBrowser, request.getKeyword(), boostConfig.getClientBrowser()));
                wrapper.should(w -> w.eq(ErrorLogDocumentDO::getClientVersion, request.getKeyword(), boostConfig.getClientVersion()));
                wrapper.should(w -> w.eq(ErrorLogDocumentDO::getOperationNickname, request.getKeyword()));
            }
            return wrapper;
        }
    }

